/*
 * Copyright (c) 2022  by Junzhao
 * THIS FILE IS PART OF JAVASE Song Huongkang PROJECT
 * All Rights Reserved.
 */

package 处理流.缓冲流;

import org.junit.Test;

import java.io.*;

/**
 * @Description 缓冲流 属于处理流
 * 为了 提高数据读写的速度Java API提供了带缓冲功能的流类，在使用这些流类
 * 时，会创建一个内部 缓冲区数组，缺省使用 8192 个 字节 8Kb) 的缓冲区 。
 * 缓冲 流要“套接”在相应的节点流之上，根据 数据操作单位可以把缓冲流分为：
 * 处理字节：BufferedInputStream 和 BufferedOutputStream
 * 处理字符：BufferedReader 和 BufferedWriter
 * 当 读取数据时，数据按块读入缓冲区，其后的读操作则直接访问 缓冲区
 * <p>
 * 当 使用 BufferedInputStream 读取字节 文件 时 BufferedInputStream 会一次性从
 * 文件中读取 8192 个 (8Kb 存在 缓冲区 中 直到 缓冲区装满 了 才 重新从文件中
 * 读取下一个 8192 个字节 数组 。
 * <p><></>
 * 向 流中写入字节 时 不会 直接写到 文件 先 写到缓冲区中直到缓冲区写 满
 * BufferedOutputStream 才会把缓冲区中的数据一次性写到文件 里 。使用方法
 * flush() 可以强制将缓冲区的内容全部写入输出流
 * <p>
 * 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可，关闭最外层流也会相应关闭内层节点流
 * <p>
 * flush() 方法的 使用：手动将 buffer 中内容写入 文件
 * 如果 是带缓冲区的流对象的 close() 方法 不但会关闭流还会在关闭流之前刷新缓冲区关闭后不能再写出
 * @Author 俊昭
 * @Date 2022/4/25
 */
public class BufferedTest {
    /**
     * 缓冲流BufferedFileOutput、InputStream实现文件复制的执行速度
     * @author 俊昭
     * @date 2022/4/25
     */
    @Test
    public void bufferedStreamTest001() {
        // 99.6 MB (104,493,563 字节) 用时163ms
        long start = System.currentTimeMillis();

        // 造文件
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            File f1 = new File("C:\\Users\\Junzhao\\IOStream\\字节流\\实例视频.mkv");
            File f2 = new File("C:\\Users\\Junzhao\\IOStream\\缓冲流\\实例视频.mkv");

            // 造流
            FileInputStream fis = new FileInputStream(f1);
            FileOutputStream fos = new FileOutputStream(f2);

            // 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            // 具体复制的细节
            byte[] bbuf = new byte[1024];
            int len;
            while ((len = bis.read(bbuf)) != - 1) {
                bos.write(bbuf, 0, len);

//                bos.flush();刷新此缓冲的输出流。这将强制将任何缓冲的输出字节写入基础输出流
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            // 关闭流 要求是先关外层再关内层 但是内层不需要手动关
            try {
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
//        fos.close();
//        fis.close();


        long end = System.currentTimeMillis();

        System.out.println("复制耗时：" + (end - start) + "毫秒");


    }

    /**
     * 缓冲流BufferedFileWriter、Reader实现文件复制的执行速度
     *
     * @author 俊昭
     * @date 2022/4/25
     */
    @Test
    public void bufferedReadWriterTest001() {
        // 32.6 MB (34,242,560 字节) 用时107ms
        long start = System.currentTimeMillis();

        // 造文件
        BufferedReader bis = null;
        BufferedWriter bos = null;
        try {
            File f1 = new File("C:\\Users\\Junzhao\\IOStream\\字符流\\Buffered.txt");
            File f2 = new File("C:\\Users\\Junzhao\\IOStream\\缓冲流\\Buffered.txt");

            // 造流
            FileReader fis = new FileReader(f1);
            FileWriter fos = new FileWriter(f2);

            // 造缓冲流
            bis = new BufferedReader(fis);
            bos = new BufferedWriter(fos);

            // 具体复制的细节
            char[] bbuf = new char[1024];
            int len = 0;
            while ((len = bis.read(bbuf)) != - 1) {
                bos.write(bbuf, 0, len);

//                bos.flush();刷新此缓冲的输出流。这将强制将任何缓冲的输出字节写入基础输出流
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            // 关闭流 要求是先关外层再关内层 但是内层不需要手动关
            try {
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
//        fos.close();
//        fis.close();


        long end = System.currentTimeMillis();

        System.out.println("复制耗时：" + (end - start) + "毫秒");


    }
}
